#include "crossbit/ELFMemoryImage.h"
#include "crossbit/VInst.h"

#include "arch/mips/MIPSInterpreter.h"
#include "arch/mips/MIPSVBasicBlockBuilder.h"

#include "MIPSInst.h"

using namespace crossbit;

namespace crossbit
{
#define INSTLEN		4

#define DELAYREG1	34
#define DELAYREG2	35
#define TEMPREG1	36
#define TEMPREG2	37
#define TEMPREG3	38 
#define TEMPREG4	39
#define TEMPREG5	40

				MIPSOpsFmt* pInst;
				MIPSProcessorState *pState;
				XTMemAddr PC;

				void deSpecial(void* arg);
				void deRegimm(void* arg);
				void deJ(void* arg);
				void deJAL(void* arg);
				void deBEQ(void* arg);
				void deBNE(void* arg);
				void deBLEZ(void* arg);
				void deBGTZ(void* arg);
				void deADDI(void* arg);
				void deADDIU(void* arg);
				void deSLTI(void* arg);
				void deSLTIU(void* arg);
				void deANDI(void* arg);
				void deORI(void* arg);
				void deXORI(void* arg);
				void deLUI(void* arg);
				void deCOP0(void* arg);
				void deCOP1(void* arg);
				void deCOP2(void* arg);
				void deCOP1X(void* arg);
				void deBEQL(void* arg);
				void deBNEL(void* arg);
				void deBLEZL(void* arg);
				void deBGTZL(void* arg);
				void deSpecial2(void* arg);
				void deJALX(void* arg);
				void deSpecial3(void* arg);
				void deLB(void* arg);
				void deLH(void* arg);
				void deLWL(void* arg);
				void deLW(void* arg);
				void deLBU(void* arg);
				void deLHU(void* arg);
				void deLWR(void* arg);
				void deSB(void* arg);
				void deSH(void* arg);
				void deSWL(void* arg); 
				void deSW(void* arg);
				void deSWR(void* arg);
				void deLL(void* arg);
				void deLWC1(void* arg);
				void deLWC2(void* arg);
				void dePREF(void* arg);
				void deLDC1(void* arg);
				void deLDC2(void* arg);
				void deSC(void* arg);
				void deSWC1(void* arg);
				void deSWC2(void* arg);
				void deSDC1(void* arg);
				void deSDC2(void* arg);
				void deUndef(void* arg);

				void deSLL(void* arg);
				void deMOVCI(void* arg);
				void deSRL(void* arg);
				void deSRA(void* arg);
				void deSLLV(void* arg);
				void deSRLV(void* arg);
				void deSRAV(void* arg);
				void deJR(void* arg);	//JR, JR.HB
				void deJALR(void* arg);	//JALR, JALR.HB
				void deMOVZ(void* arg);
				void deMOVN(void* arg);
				void deSYSCALL(void* arg);
				void deBREAK(void* arg);
				void deSYNC(void* arg);
				void deMFHI(void* arg);
				void deMTHI(void* arg);
				void deMFLO(void* arg);
				void deMTLO(void* arg);
				void deMULT(void* arg);
				void deMULTU(void* arg);
				void deDIV(void* arg);
				void deDIVU(void* arg);
				void deADD(void* arg);
				void deADDU(void* arg);
				void deSUB(void* arg);
				void deSUBU(void* arg);
				void deAND(void* arg);
				void deOR(void* arg);
				void deXOR(void* arg);
				void deNOR(void* arg);
				void deSLT(void* arg);
				void deSLTU(void* arg);
				void deTGE(void* arg);
				void deTGEU(void* arg);
				void deTLT(void* arg);
				void deTLTU(void* arg);
				void deTEQ(void* arg);
				void deTNE(void* arg);

				void deBLTZ(void* arg);
				void deBGEZ(void* arg);
				void deBLTZL(void* arg);
				void deBGEZL(void* arg);
				void deTGEI(void* arg);
				void deTGEIU(void* arg);
				void deTLTI(void* arg);
				void deTLTIU(void* arg);
				void deTEQI(void* arg);
				void deTNEI(void* arg);
				void deBLTZAL(void* arg);
				void deBGEZAL(void* arg);
				void deBLTZALL(void* arg);
				void deBGEZALL(void* arg);
				void deSYNCI(void* arg);

				//COP1
				void deCOP1S(void* arg);
				void deMFC1(void* arg);
				void deCFC1(void* arg);
				void deMTC1(void* arg);
				void deCTC1(void* arg);
				void deBC1(void* arg);
				void deCOP1D(void* arg);
				void deCOP1W(void* arg);

				void deADD_S(void* arg);
				void deADD_D(void* arg);
				void deSUB_S(void* arg);
				void deSUB_D(void* arg);
				void deDIV_S(void* arg);
				void deDIV_D(void* arg);
				void deMUL_S(void* arg);
				void deMUL_D(void* arg);
				void deABS_S(void* arg);
				void deABS_D(void* arg);
				void deMOV_S(void* arg);
				void deMOV_D(void* arg);
				void deNEG_S(void* arg);
				void deNEG_D(void* arg);
				void deCVT_W_D(void* arg);
				void deC_EQ_S(void* arg);
				void deC_EQ_D(void* arg);
				void deC_ULE_S(void* arg);
				void deC_LT_S(void* arg);
				void deC_LT_D(void* arg);
				void deC_LE_S(void* arg);
				void deC_LE_D(void* arg);

				void deCVT_D_S(void* arg);
				void deCVT_W_S(void* arg);
				void deCVT_S_W(void* arg);
				void deCVT_D_W(void* arg);

				void deCVT_S_D(void* arg);

				typedef void (*Defunc)(void*);

				typedef struct
				{
								XTPStr name;
								Defunc f;
				} FuncTable;

				FuncTable deTable[] = 
				{ 											//op:
								{"SPECIAL", deSpecial}, {"REGIMM", deRegimm}, {"J", deJ}, {"JAL", deJAL},	//0 - 4
								{"BEQ", deBEQ}, {"BNE", deBNE}, {"BLEZ", deBLEZ}, {"BGTZ", deBGTZ},
								{"ADDI", deADDI}, {"ADDIU", deADDIU}, {"SLTI", deSLTI}, {"SLTIU", deSLTIU},
								{"ANDI", deANDI}, {"ORI", deORI}, {"XORI", deXORI}, {"LUI", deLUI},
								{"Undef", deUndef},{"COP1", deCOP1},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},	
								{"LB", deLB},{"LH", deLH},{"LWL", deLWL},{"LW", deLW},
								{"LBU", deLBU},{"LHU", deLHU},{"LWR", deLWR},{"Undef", deUndef},
								{"SB", deSB},{"SH", deSH},{"SWL", deSWL},{"SW", deSW},
								{"Undef", deUndef},{"Undef", deUndef},{"SWR", deSWR},{"Undef", deUndef},
								{"LL", deLL},{"LWC1", deLWC1},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"SC", deSC},{"SWC1", deSWC1},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef}
				};

				FuncTable deSpecialTable[] = 
				{
								{"SLL", deSLL},{"Undef", deUndef},{"SRL", deSRL},{"SRA", deSRA},
								{"SLLV", deSLLV},{"Undef", deUndef},{"SRLV", deSRLV},{"SRAV", deSRAV},
								{"JR", deJR},{"JALR", deJALR},{"Undef", deUndef},{"Undef", deUndef},
								{"SYSCALL", deSYSCALL},{"BREAK", deBREAK},{"Undef", deUndef},{"Undef", deUndef},
								{"MFHI", deMFHI},{"Undef", deUndef},{"MFLO", deMFLO},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"MULT", deMULT},{"MULTU", deMULTU},{"DIV", deDIV},{"DIVU", deDIVU},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"ADDU", deADDU},{"Undef", deUndef},{"SUBU", deSUBU},
								{"AND", deAND},{"OR", deOR},{"XOR", deXOR},{"NOR", deNOR},
								{"Undef", deUndef},{"Undef", deUndef},{"SLT", deSLT},{"SLTU", deSLTU},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef}
				};

				FuncTable deRegimmTable[]  = 
				{
								{"BLTZ", deBLTZ},{"BGEZ", deBGEZ},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"BLTZAL", deBLTZAL},{"BGEZAL", deBGEZAL},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef}
				};

				FuncTable deCOP1Table[] = 
				{
								{"MFC1", deMFC1},{"Undef", deUndef},{"CFC1", deCFC1},{"Undef", deUndef},
								{"MTC1", deMTC1},{"Undef", deUndef},{"CTC1", deCTC1},{"Undef", deUndef},
								{"BC1", deBC1},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"cop1s", deCOP1S},{"cop1d", deCOP1D},{"Undef", deUndef},{"Undef", deUndef},
								{"cop1w", deCOP1W},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef}
				};

				FuncTable deCOP1STable[]  =
				{
								{"ADD.S", deADD_S},{"SUB.S", deSUB_S},{"MUL_S", deMUL_S},{"DIV.S", deDIV_S},
								{"Undef", deUndef},{"ABS.S", deABS_S},{"MOV.S", deMOV_S},{"NEG.S", deNEG_S},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"CVT.D.S", deCVT_D_S},{"Undef", deUndef},{"Undef", deUndef},
								{"CVT.W.S", deCVT_W_S},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"C.EQ.S", deC_EQ_S},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"C.ULE.S", deC_ULE_S},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"C.LT.S", deC_LT_S},{"Undef", deUndef},{"C.LE.S", deC_LE_S},{"Undef", deUndef}
				};

				FuncTable deCOP1DTable[]  =
				{
								{"ADD.D", deADD_D},{"SUB.D", deSUB_D},{"MUL_D", deMUL_D},{"DIV_D", deDIV_D},
								{"Undef", deUndef},{"ABS.D", deABS_D},{"MOV.D", deMOV_D},{"NEG.D", deNEG_D},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"CVT.S.D", deCVT_S_D},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"CVT.W", deCVT_W_D},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"C.EQ", deC_EQ_D},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"C.LT", deC_LT_D},{"Undef", deUndef},{"C.LE", deC_LE_D},{"Undef", deUndef}
				};

				FuncTable deCOP1WTable[]  =
				{
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"CVT.S.W", deCVT_S_W},{"CVT.D", deCVT_D_W},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},
								{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef},{"Undef", deUndef}
				};


				void deSpecial(void* arg)
				{
								deSpecialTable[pInst->func].f(arg);
				}

				void deRegimm(void* arg)
				{
								deRegimmTable[pInst->bl].f(arg);
				}

				void deCOP1(void* arg)
				{
								deCOP1Table[pInst->rs].f(arg);
				}

				void deCOP1S(void* arg)
				{
								deCOP1STable[pInst->func].f(arg);
				}

				void deCOP1D(void* arg)
				{
								deCOP1DTable[pInst->func].f(arg);
				}

				void deCOP1W(void* arg)
				{
								deCOP1WTable[pInst->func].f(arg);
				}

				void deJ(void* arg)
				{/*
						unsigned int w = *((unsigned int*)arg);
						unsigned target = ((w&0x03ffffff) << 2) |((PC+INSTLEN)&0xf0000000);
					*/
								printf("0x%08x\n", PC);
								exit(1);
				}

				void deJAL(void* arg)
				{
								printf("0x%08x\n", PC);
								exit(1);
				}

				void deBEQ(void* arg)
				{
								unsigned address = PC + 4 + ((signed short)pInst->offset <<2 );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rt, DELAYREG2) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(EQ, DELAYREG1, DELAYREG2, 0, address) );

								PC = PC + 4;
				}

				void deBNE(void* arg)
				{
								unsigned address = PC + 4 + ((signed short)pInst->offset <<2 );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rt, DELAYREG2) );

								pInst = (MIPSOpsFmt*)(PC+4);

								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(NE, DELAYREG1, DELAYREG2, 0, address) );

								PC = PC + 4;
				}

				void deBLEZ(void* arg)
				{
								unsigned address = PC + 4 + ((signed short)pInst->offset << 2 );

								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(LE, DELAYREG1, 0, 0, address) );

								PC = PC + 4;
				}

				void deBGTZ(void* arg)
				{
								unsigned address = PC + 4 + ((signed short)pInst->offset << 2 );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(GT, DELAYREG1, 0, 0, address) );
								PC = PC + 4;
				}

				void deADDI(void* arg)
				{
								printf("0x%08x\n", PC);
								exit(1);
				}

				void deADDIU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI(((int)(signed short)pInst->offset), TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD( TEMPREG1, pInst->rrs, pInst->bl) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT( pInst->bl, pInst->bl) );
				}

				void deSLTI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI((int)(signed short)pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( CMP(LT, pInst->rs, TEMPREG1, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT( pInst->rt, pInst->rt) );
				}

				void deSLTIU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI((int)(signed short)pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( CMP(BE, pInst->rs, TEMPREG1, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT( pInst->rt, pInst->rt) );
				}

				void deANDI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG1, pInst->rs, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deORI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(TEMPREG1, pInst->rrs, pInst->bl) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->bl, pInst->bl) );
				}

				void deXORI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( XOR(TEMPREG1, pInst->rs, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deLUI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI((pInst->offset<<16), pInst->bl) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->bl, pInst->bl));
				}

				void deLB(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD( pInst->rs, 
																												 ((int)(signed short)pInst->offset), BYTE, pInst->rt) );        
								((MIPSVBasicBlockBuilder*)arg)->add( SEXT(pInst->rt, BYTE, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) ); 
				}

				void deLH(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(pInst->rs,
																												((int)(signed short)pInst->offset), HALFWORD, pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( SEXT(pInst->rt, HALFWORD, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deLWL(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD(pInst->rs, TEMPREG1, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xfffffffc, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG5, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(TEMPREG2, 0, WORD, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x3, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG5, TEMPREG1, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG5, TEMPREG1, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(24, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( SUB(TEMPREG3, TEMPREG5, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG2, TEMPREG3, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xffffffff, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG4, TEMPREG3, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( NOT(TEMPREG4, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(pInst->rt, TEMPREG4, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(pInst->rt, TEMPREG2, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deLWR(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD(pInst->rs, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xfffffffc, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG4, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(TEMPREG2, 0, WORD, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x3, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG4, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG4, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(TEMPREG2, TEMPREG4, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xffffffff, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(TEMPREG3, TEMPREG4, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( NOT(TEMPREG3, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(pInst->rt, TEMPREG3, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(pInst->rt, TEMPREG2, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deLW(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD( pInst->rrs, 
																												 ((int)(signed short)pInst->offset), WORD, pInst->bl) );        
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->bl, pInst->bl) ); 
				}

				void deLBU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(pInst->rs, 
																												((int)(signed short)pInst->offset), BYTE, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( ZEXT(pInst->rt, BYTE, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deLHU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD( pInst->rs, 
																												 ((int)(signed short)pInst->offset), HALFWORD, pInst->rt) );        
								((MIPSVBasicBlockBuilder*)arg)->add( ZEXT(pInst->rt, HALFWORD, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) ); 
				}

				void deSB(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(pInst->rt, BYTE, pInst->rs, ((int)(signed short)pInst->offset)) );
				}

				void deSH(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(pInst->rt, HALFWORD, 
																												pInst->rs, ((int)(signed short)pInst->offset)) );
				}

				void deSWL(void* arg)	//added newly
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD(pInst->rs, TEMPREG1, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xfffffffc, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG1, TEMPREG2, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(TEMPREG3, 0, WORD, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x3, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG1, TEMPREG2, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG1, TEMPREG2, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(24, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( SUB(TEMPREG2, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(pInst->rt, TEMPREG2, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xffffffff, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(TEMPREG1, TEMPREG2, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( NOT(TEMPREG1, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG4, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(TEMPREG4, TEMPREG5, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(TEMPREG4, WORD, TEMPREG3, 0) );
				}

				void deSWR(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->offset, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD(pInst->rs, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xfffffffc, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG4, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(TEMPREG2, 0, WORD, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x3, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG4, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG4, TEMPREG1, TEMPREG4) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(pInst->rt, TEMPREG4, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0xffffffff, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(TEMPREG1, TEMPREG4, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( NOT(TEMPREG1, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(TEMPREG3, TEMPREG1, TEMPREG3) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(TEMPREG5, TEMPREG3, TEMPREG5) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(TEMPREG5, WORD, TEMPREG2, 0) );
				}

				void deLL(void* arg)	//an atomic read, simply equal lw now
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD( pInst->rrs, 
																												 ((int)(signed short)pInst->offset), WORD, pInst->bl) );        
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->bl, pInst->bl) ); 
				}

				void deLWC1(void* arg)	//added newly
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( FLD(pInst->rs, 
																												 ((int)(signed short)pInst->offset), WORD, pInst->rt) );
				}

				void deSC(void* arg)	//an atomic write, simply equal sw now
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->bl, pInst->bl) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(pInst->bl, 
																												WORD, pInst->rrs, ((int)(signed short)pInst->offset)) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(1, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(TEMPREG1, pInst->bl));
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->bl, pInst->bl) );
				}

				void deSWC1(void* arg)	//added newly
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( FST(pInst->rt, 
																												 WORD, pInst->rs, ((int)(signed short)pInst->offset)) );

				}

				void deSW(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->bl, pInst->bl) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(pInst->bl, 
																												WORD, pInst->rrs, ((int)(signed short)pInst->offset)) );
				}

				void deSLL(void* arg)
				{
								if( pInst->ze == 0 && pInst->rt == 0 && pInst->rd == 0 )
								{
												//do nothing
								}
								else if( pInst->ze == 1 && pInst->rt == 0 && pInst->rd == 0 )
								{
												//do nothing
								}
								else
								{
												((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->ze, TEMPREG1) );
												((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt));
												((MIPSVBasicBlockBuilder*)arg)->add( SLL(pInst->rt, TEMPREG1, pInst->rd) );
												((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd));
								}
				}

				void deMOVCI(void* arg);

				void deSRL(void* arg)	//don't consider ROTR
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->ze, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(pInst->rt, TEMPREG1, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSRA(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(pInst->ze, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRA(pInst->rt, TEMPREG1, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSLLV(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x1f, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(pInst->rs, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( SLL(pInst->rt, TEMPREG2, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSRLV(void* arg)
				{	
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x1f, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(pInst->rs, TEMPREG1, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRL(pInst->rt, TEMPREG2, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSRAV(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( LI(0x1f, TEMPREG1) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND( TEMPREG1, pInst->rs, TEMPREG2) );
								((MIPSVBasicBlockBuilder*)arg)->add( SRA(pInst->rt, TEMPREG2, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deJR(void* arg)	//JR, JR.HB
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( JMP(DELAYREG1, 0) );

								PC = PC + 4;
				}

				void deMOVZ(void* arg);
				void deMOVN(void* arg);
				void deSYSCALL(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( SYSCALL );
				}

				void deBREAK(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( HALT(PC) );
				}

				void deSYNC(void* arg);

				void deMFHI(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(32, 32) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(32, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deMTHI(void* arg);

				void deMFLO(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(33, 33) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(33, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deMTLO(void* arg);
				void deMULT(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( MUL(pInst->rs, pInst->rt, 32, 33) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(32, 32) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(33, 33) );
				}

				void deMULTU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( MULU(pInst->rs, pInst->rt, 32, 33) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(32, 32) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(33, 33) );
				}

				void deDIV(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( DIV(pInst->rs, pInst->rt, 33, 32) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(33, 33) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(32, 32) );
				}

				void deDIVU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( DIVU(pInst->rs, pInst->rt, 33, 32) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(33, 33) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(32, 32) );
				}

				void deADD(void* arg);
				void deSUB(void* arg);

				void deSUBU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( SUB(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deOR(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deXOR(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( XOR(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deNOR(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( OR(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( NOT(pInst->rd, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSLT(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( CMP(LT, pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deSLTU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( CMP(BE, pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deTGE(void* arg);
				void deTGEU(void* arg);
				void deTLT(void* arg);
				void deTLTU(void* arg);
				void deTEQ(void* arg);
				void deTNE(void* arg);


				void deJALR(void* arg) //JALR, JALR.HB
				{
								((MIPSVBasicBlockBuilder*)arg)->add( LI((PC+8), pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT( pInst->rd, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET( pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV( pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( JMP(DELAYREG1,0) );

								PC = PC + 4;
				}

				void deADDU(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( ADD(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deAND(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( AND(pInst->rs, pInst->rt, pInst->rd) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rd, pInst->rd) );
				}

				void deBLTZ(void* arg)
				{
								unsigned address = (PC+4+(((signed short)pInst->offset) <<2) );

								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(LT, DELAYREG1, 0, 0, address) );

								PC = PC + 4;
				}

				void deBGEZ(void* arg)
				{
								unsigned address = PC + 4 + (((signed short)pInst->offset) << 2);

								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(GE, DELAYREG1, 0, 0, address) );

								PC = PC + 4;
				}

				void deBLTZL(void* arg);
				void deBGEZL(void* arg);
				void deTGEI(void* arg);
				void deTGEIU(void* arg);
				void deTLTI(void* arg);
				void deTLTIU(void* arg);
				void deTEQI(void* arg);
				void deTNEI(void* arg);

				void deBLTZAL(void* arg)
				{
								unsigned address = (PC + 4 + (((signed short)pInst->offset) <<2));
								((MIPSVBasicBlockBuilder*)arg)->add( LI(PC+8, 31) );		//$ra : 31
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(31, 31) );		//$ra : 31

								/**
								 * As delay slot will be executed first, so we should store
								 * the operand in a reg which will not be used in the delay slot
								 */
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rrs, pInst->rrs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rrs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(LT, DELAYREG1, 0, 0, address) );

								PC = PC + 4;
				}

				void deBGEZAL(void* arg)
				{
								unsigned int address = PC + 4 + ((signed short)pInst->offset << 2);
								((MIPSVBasicBlockBuilder*)arg)->add( LI(PC+8, 31) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(31, 31) );
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rs, pInst->rs) );
								((MIPSVBasicBlockBuilder*)arg)->add( MOV(pInst->rs, DELAYREG1) );

								pInst = (MIPSOpsFmt*)(PC+4);
								deTable[pInst->op].f(arg);

								((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(GE, DELAYREG1, 0, 0, address) );

								PC = PC + 4;
				}

				void deBLTZALL(void* arg);
				void deBGEZALL(void* arg);
				void deSYNCI(void* arg);

				void deMFC1(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FST(pInst->rd, WORD, 0, pState->get(pInst->rt)) );
								((MIPSVBasicBlockBuilder*)arg)->add( LD(0, pState->get(pInst->rt), WORD, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( PUT(pInst->rt, pInst->rt) );
				}

				void deCFC1(void* arg)
				{
								//dummy
								//printf("use instruction CFC1\n");
								//exit(1);
								//((MIPSVBasicBlockBuilder*)arg)->add( FST(pInst->rd, WORD, 0, interp_state->get(pInst->rt)) );
				}

				void deMTC1(void* arg)	//added newly
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( GET(pInst->rt, pInst->rt) );
								((MIPSVBasicBlockBuilder*)arg)->add( ST(pInst->rt, WORD, 0, pState->get(pInst->rt)) );
								((MIPSVBasicBlockBuilder*)arg)->add( FLD(0, pState->get(pInst->rt), WORD, pInst->rd) );
				}

				void deCTC1(void* arg)
				{
								//dummy
								//printf("use instruction CTC1\n");
								//exit(1);
								//((MIPSVBasicBlockBuilder*)arg)->add( FLD(0, interp_state->get(pInst->rt), WORD, pInst->rd) );
				}

				void deBC1(void* arg)
				{
								//printf("PC 0x%08x, \n", PC);

								if(pInst->rt == 1)
								{
												//printf("BC1T\n");

												unsigned int address = PC + 4 + ((signed short)pInst->offset << 2);

												((MIPSVBasicBlockBuilder*)arg)->add( LD(0, pState->fpGet(MIPSProcessorState::$fcc), WORD, DELAYREG1));

												pInst = (MIPSOpsFmt*)(PC+4);
												deTable[pInst->op].f(arg);

												((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(NE, 0, DELAYREG1, 0, address) );
												PC = PC + 4;
								}
								else if(pInst->rt == 0)
								{
												//printf("BC1F\n");

												unsigned int address = PC + 4 + ((signed short)pInst->offset << 2);

												((MIPSVBasicBlockBuilder*)arg)->add( LD(0, pState->fpGet(MIPSProcessorState::$fcc), WORD, DELAYREG1));

												pInst = (MIPSOpsFmt*)(PC+4);
												deTable[pInst->op].f(arg);

												((MIPSVBasicBlockBuilder*)arg)->add( BRANCH(EQ, 0, DELAYREG1, 0, address) );

												PC = PC + 4;
								}
				}

				void deADD_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FADDS() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deADD_D(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FADDD() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deSUB_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FSUBS() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deSUB_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FSUBD() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deMUL_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FMULS() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deMUL_D(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FMULD() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deDIV_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FDIVS() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deDIV_D(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rt));
								((MIPSVBasicBlockBuilder*)arg)->add( FDIVD() );
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deABS_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FABSS());
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deABS_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FABSD());
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deMOV_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deMOV_D(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
				}

				void deNEG_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETS(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FNEGS());
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTS(pInst->ze));
				}

				void deNEG_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FGETD(pInst->rd));
								((MIPSVBasicBlockBuilder*)arg)->add( FNEGD());
								((MIPSVBasicBlockBuilder*)arg)->add( FPUTD(pInst->ze));
								//printf("PC: 0x%08x: neg.d\n", PC);
				}

				void deCVT_W_D(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, DOUBLE, pInst->ze, WORD) );
				}

				void deC_EQ_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPS(EQ, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
				}

				void deC_EQ_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPD(EQ, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
								//printf("PC:0x%08x, c.eq.d\n", PC);
				}

				void deC_ULE_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPS(NA, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
				}

				void deC_LT_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPS(BE, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
				}

				void deC_LT_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPD(BE, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
								//printf("PC:0x%08x, c.lt.d\n", PC);
				}

				void deC_LE_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPS(NA, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
				}

				void deC_LE_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCMPD(NA, pInst->rd, pInst->rt, MIPSProcessorState::$fcc) );
								//printf("PC:0x%08x, c.le.d\n", PC);
				}

				void deCVT_D_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, FLOAT, pInst->ze, DOUBLE) );
				}

				void deCVT_W_S(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, FLOAT, pInst->ze, WORD) );
				}

				void deCVT_S_W(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, WORD, pInst->ze, FLOAT) );
				}

				void deCVT_D_W(void* arg)
				{
								//deUndef(arg);
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, WORD, pInst->ze, DOUBLE) );
				}

				void deCVT_S_D(void* arg)
				{
								((MIPSVBasicBlockBuilder*)arg)->add( FCONV(pInst->rd, DOUBLE, pInst->ze, FLOAT) );
				}

				void deUndef(void* arg)
				{
								printf("0x%08x:\t", PC);
								printf("Undef instruction: 0x%08x\n", *(int*)arg);
								exit(1);
				} 
}

void MIPSInterpreter::delaySlot( XTMemAddr addr )
{
				//MIPSOpsFmt* inst = (MIPSOpsFmt*)(mm_->map(PC));
				MIPSOpsFmt* inst = (MIPSOpsFmt*)(PC);
				deTable[inst->op].f( inst );
}

XTInt32 MIPSInterpreter::initStack(XTMemAddr sp)
{
				interp_state->put( 29, sp ); 
				return 0;
}

XTMemAddr MIPSInterpreter::decode(XTMemAddr at, VBlockBuilder *bb)
{
				PC = at;
				//			pInst = (MIPSOpsFmt*)(mm_->map(PC));
				pInst = (MIPSOpsFmt*)(PC);
				pState = (MIPSProcessorState*)(interp_state);
				deTable[pInst->op].f( bb );

				return (PC+4); 
}
